import { NativeModules, Platform } from 'react-native';
import { DlnaError, DlnaErrorCode } from './errors';
import { Device } from './types';

// 错误信息常量
const LINKING_ERROR =
  `The package 'react-native-dlna-player' doesn't seem to be linked. Make sure: \n\n` +
  Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
  '- You rebuilt the app after installing the package\n' +
  '- You are not using Expo Go\n';

/**
 * 获取原生模块
 * @returns 原生模块实例
 */
export function getNativeModule() {
  return NativeModules.DlnaPlayer
    ? NativeModules.DlnaPlayer
    : new Proxy(
        {},
        {
          get() {
            throw new Error(LINKING_ERROR);
          },
        }
      );
}

// 获取原生模块
export const DlnaPlayerModule = getNativeModule();

/**
 * 验证URL
 * @param url 要验证的URL
 * @returns 验证后的URL
 * @throws {DlnaError} 如果URL无效
 */
export const validateUrl = (url: string): string => {
  if (!url || typeof url !== 'string') {
    throw DlnaError.invalidParameter('url', 'URL不能为空');
  }
  
  try {
    new URL(url);
  } catch (e) {
    throw DlnaError.invalidParameter('url', '无效的URL格式');
  }
  
  return url;
};

/**
 * 验证设备ID
 * @param deviceId 要验证的设备ID
 * @returns 验证后的设备ID
 * @throws {DlnaError} 如果设备ID无效
 */
export const validateDeviceId = (deviceId: string): string => {
  if (!deviceId || typeof deviceId !== 'string') {
    throw DlnaError.invalidParameter('deviceId', '设备ID不能为空');
  }
  return deviceId;
};

/**
 * 验证音量
 * @param volume 要验证的音量值
 * @returns 验证后的音量值
 * @throws {DlnaError} 如果音量无效
 */
export const validateVolume = (volume: number): number => {
  if (typeof volume !== 'number') {
    throw DlnaError.invalidParameter('volume', '音量必须是数字');
  }
  
  if (volume < 0 || volume > 100) {
    throw DlnaError.invalidParameter('volume', '音量必须在0-100范围内');
  }
  
  return volume;
};

/**
 * 验证播放位置
 * @param position 要验证的播放位置
 * @returns 验证后的播放位置
 * @throws {DlnaError} 如果播放位置无效
 */
export const validatePosition = (position: number): number => {
  if (typeof position !== 'number') {
    throw DlnaError.invalidParameter('position', '位置必须是数字');
  }
  
  if (position < 0) {
    throw DlnaError.invalidParameter('position', '位置不能为负数');
  }
  
  return position;
};

/**
 * 创建一个带有超时的Promise
 * @param promise 原始Promise
 * @param timeoutMs 超时时间（毫秒）
 * @param errorMsg 超时错误消息
 * @returns 带有超时的Promise
 */
export const withTimeout = <T>(
  promise: Promise<T>,
  timeoutMs: number = 10000,
  errorMsg: string = '操作超时'
): Promise<T> => {
  const timeoutPromise = new Promise<T>((_, reject) => {
    setTimeout(() => {
      reject(new DlnaError(DlnaErrorCode.TIMEOUT, errorMsg));
    }, timeoutMs);
  });

  return Promise.race([promise, timeoutPromise]);
};

// 设备缓存
export const deviceCache = {
  cache: new Map<string, { device: Device; timestamp: number }>(),
  
  // 缓存过期时间（毫秒）
  expireTime: 5 * 60 * 1000, // 5分钟
  
  /**
   * 添加设备到缓存
   * @param device 设备对象
   */
  addDevice(device: Device): void {
    this.cache.set(device.id, {
      device,
      timestamp: Date.now(),
    });
  },
  
  /**
   * 添加多个设备到缓存
   * @param devices 设备列表
   */
  addDevices(devices: Device[]): void {
    devices.forEach(device => this.addDevice(device));
  },
  
  /**
   * 从缓存获取设备
   * @param deviceId 设备ID
   * @returns 设备对象或undefined
   */
  getDevice(deviceId: string): Device | undefined {
    const cachedItem = this.cache.get(deviceId);
    if (!cachedItem) return undefined;
    
    const { device, timestamp } = cachedItem;
    if (Date.now() - timestamp > this.expireTime) {
      this.cache.delete(deviceId);
      return undefined;
    }
    
    return device;
  },
  
  /**
   * 获取所有缓存的设备
   * @param filterExpired 是否过滤过期设备
   * @returns 设备列表
   */
  getAllDevices(filterExpired: boolean = true): Device[] {
    const devices: Device[] = [];
    const now = Date.now();
    
    this.cache.forEach((cachedItem, deviceId) => {
      const { device, timestamp } = cachedItem;
      if (!filterExpired || now - timestamp <= this.expireTime) {
        devices.push(device);
      } else if (filterExpired) {
        this.cache.delete(deviceId);
      }
    });
    
    return devices;
  },
  
  /**
   * 清除缓存
   */
  clear(): void {
    this.cache.clear();
  },
  
  /**
   * 清除过期设备
   */
  clearExpired(): void {
    const now = Date.now();
    this.cache.forEach((cachedItem, deviceId) => {
      if (now - cachedItem.timestamp > this.expireTime) {
        this.cache.delete(deviceId);
      }
    });
  }
}; 